package com.qst.order.controller;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.qst.order.domain.*;
import com.qst.order.domain.DTO.ReturnApplyDTO;
import com.qst.order.mapper.ReturnApplyItemMapper;
import com.qst.order.service.*;
import com.qst.order.utils.JwtUtil;
import com.qst.order.utils.Result;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/returnApply")
public class ReturnApplyController {

    private final ReturnApplyService returnApplyService;
    private final OrderService orderService;
    private final OrderItemService orderItemService;
    private final ReturnApplyItemMapper returnApplyItemMapper;
    private final JwtUtil jwtUtil;
    private final UserService userService;
    private final OrderPayService orderPayService;

    /**
     * 提交退货申请（仅处理已发货和部分发货的订单）
     */
    /**
     * 提交退货申请（处理已发货和部分发货订单，动态计算退款金额）
     */
    @PostMapping("/apply")
    @Transactional
    public Result apply(
            @Validated @RequestBody ReturnApplyDTO applyDTO,
            @RequestHeader("Authorization") String token) {

        log.info("收到退货申请: {}", applyDTO);
        String username = jwtUtil.getClaim(token, "username");
        Integer orderId = applyDTO.getOrderId();

        // 1. 查询订单及验证状态
        Order order = orderService.getById(orderId);
        if (order == null) {
            return Result.error("订单不存在");
        }


        List<String> validStatus = List.of("shipped", "pending_receive", "completed","partial_received");
        log.warn("订单状态:{}",validStatus.contains(order.getStatus()));
        if (!validStatus.contains(order.getStatus())) {
            return Result.error("仅已发货、部分发货或已完成的订单可申请退款");
        }

        // 2. 查询申请退货的订单项
        List<String> itemNos = applyDTO.getItems().stream()
                .map(ReturnApplyItem::getItemNo)
                .collect(Collectors.toList());

        List<OrderItem> targetItems = orderItemService.lambdaQuery()
                .eq(OrderItem::getOrderId, orderId)
                .in(OrderItem::getItemNo, itemNos)
                .list();

        if (targetItems.isEmpty()) {
            return Result.error("未找到对应的订单项");
        }

        // 3. 验证订单项状态
        boolean hasInvalidItem = targetItems.stream()
                .anyMatch(item -> !List.of("pending","paid","shipped", "delivered").contains(item.getItemStatus()));
        if (hasInvalidItem) {
            return Result.error("操作失败");
        }

        // 4. 计算退款总金额（不存储，动态计算）
        Map<String, OrderItem> itemMap = targetItems.stream()
                .collect(Collectors.toMap(OrderItem::getItemNo, item -> item));

        BigDecimal refundAmount = calculateRefundAmount(applyDTO.getItems(), itemMap);
        if (refundAmount.compareTo(BigDecimal.ZERO) <= 0) {
            return Result.error("退款金额必须大于0");
        }

        // 5. 保存退货主表（无退款金额字段）
        ReturnApply returnApply = new ReturnApply();
        returnApply.setUsername(username);
        returnApply.setOrderId(applyDTO.getOrderId());
        returnApply.setOrderNo(applyDTO.getOrderNo());
        returnApply.setReason(applyDTO.getReason());
        returnApply.setStatus(0); // 0-待处理
        returnApply.setCreateTime(LocalDateTime.now());
        returnApply.setUpdateTime(LocalDateTime.now());
        returnApplyService.save(returnApply);
        Integer returnId = returnApply.getReturnId();

        // 6. 保存退货明细表（无单个明细退款金额字段）
        List<ReturnApplyItem> items = applyDTO.getItems().stream()
                .peek(item -> {
                    item.setReturnId(returnId);
                    if (item.getReason() == null) {
                        item.setReason(applyDTO.getReason());
                    }
                })
                .toList();
        returnApplyService.saveItems(items);

        // 7. 进入退款审核流程
        handleRefundReview(applyDTO, itemNos);

        // 返回计算的退款金额（不存储到数据库）
        Map<String, Object> result = new HashMap<>();
        result.put("returnId", returnId);
        result.put("refundAmount", refundAmount);
        return Result.success("退货申请提交成功，待商家审核", result);
    }



    /**
     * 计算退款总金额
     */
    private BigDecimal calculateRefundAmount(List<ReturnApplyItem> applyItems, Map<String, OrderItem> itemMap) {
        return applyItems.stream()
                .map(item -> {
                    OrderItem orderItem = itemMap.get(item.getItemNo());
                    return orderItem.getUnitPrice()
                            .multiply(BigDecimal.valueOf(item.getRefundQuantity()));
                })
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * 处理已发货/部分发货订单的退款审核流程
     */
    private void handleRefundReview(ReturnApplyDTO applyDTO, List<String> itemNos) {
        // 更新订单状态为"退款中"
        boolean updateResult = orderService.lambdaUpdate()
                .set(Order::getStatus, "refunding")
                .eq(Order::getOrderId, applyDTO.getOrderId())
                .update();

        if (!updateResult) {
            log.warn("订单状态更新失败，订单ID: {}", applyDTO.getOrderId());
            throw new RuntimeException("订单状态更新失败");
        }

        // 更新订单项状态为"退款中"
        boolean itemUpdateResult = orderItemService.lambdaUpdate()
                .set(OrderItem::getItemStatus, "refunding")
                .in(OrderItem::getItemNo, itemNos)
                .eq(OrderItem::getOrderId, applyDTO.getOrderId())
                .update();

        if (!itemUpdateResult) {
            log.warn("订单项状态更新失败，订单项编号: {}", itemNos);
            throw new RuntimeException("订单项状态更新失败");
        }
    }



    /**
     * 商家审核通过退款申请（实际退款操作）
     */
/*
    @PostMapping("/approve/{returnId}")
    @Transactional
    public Result approveRefund(@PathVariable Integer returnId) {
        // 1. 查询退货申请信息
        ReturnApply returnApply = returnApplyService.getById(returnId);
        if (returnApply == null) {
            return Result.error("退货申请不存在");
        }

        // 2. 验证状态：仅待审核状态可处理
        if (returnApply.getStatus() != 0) {
            return Result.error("该申请已处理，无法重复操作");
        }

        // 3. 调用支付服务执行退款
        log.info("执行退款操作，订单号: {}, 退款金额: {}",
                returnApply.getOrderNo(), returnApply.getRefundAmount());

        boolean refundSuccess = payService.refund(
                returnApply.getOrderNo(),
                returnApply.getRefundAmount(),
                returnId.toString() // 退款单号，使用退货申请ID
        );

        if (!refundSuccess) {
            log.error("支付平台退款失败，订单号: {}", returnApply.getOrderNo());
            throw new RuntimeException("退款失败，请稍后重试");
        }

        // 4. 更新退货申请状态为"已完成"
        returnApplyService.lambdaUpdate()
                .set(ReturnApply::getStatus, 2) // 2-已完成
                .set(ReturnApply::getUpdateTime, LocalDateTime.now()) // 记录退款时间
                .eq(ReturnApply::getReturnId, returnId)
                .update();

        // 5. 更新订单状态为"已退款"（如果是全部退款）
        // 查询该订单的所有订单项
        List<OrderItem> allItems = orderItemService.lambdaQuery()
                .eq(OrderItem::getOrderId, returnApply.getOrderId())
                .list();

        // 查询该订单的所有退款项
        List<ReturnApplyItem> refundItems = returnApplyService.queryItemsByReturnId(returnId);
        List<String> refundItemNos = refundItems.stream()
                .map(ReturnApplyItem::getItemNo)
                .collect(Collectors.toList());

        // 判断是否为全部退款
        boolean isFullRefund = allItems.stream()
                .allMatch(item -> refundItemNos.contains(item.getItemNo()));

        if (isFullRefund) {
            orderService.lambdaUpdate()
                    .set(Order::getStatus, "refunded")
                    .eq(Order::getOrderId, returnApply.getOrderId())
                    .update();
        } else {
            // 部分退款，订单状态保持为已完成
            orderService.lambdaUpdate()
                    .set(Order::getStatus, "completed")
                    .eq(Order::getOrderId, returnApply.getOrderId())
                    .update();
        }

        // 6. 更新订单项状态为"已退款"
        orderItemService.lambdaUpdate()
                .set(OrderItem::getItemStatus, "refunded")
                .in(OrderItem::getItemNo, refundItemNos)
                .eq(OrderItem::getOrderId, returnApply.getOrderId())
                .update();

        return Result.success("退款成功", returnApply.getRefundAmount());
    }


*/
    /**
     * 商家审核通过退款申请（动态计算退款金额）
     */
    @PostMapping("/approve/{returnId}")
    @Transactional
    public Result approveRefund(@PathVariable Integer returnId,@RequestHeader("Authorization") String token) {
        // 1. 查询退货申请信息

        String userId = jwtUtil.getClaim(token, "userId");

        ReturnApply returnApply = returnApplyService.getById(returnId);
        if (returnApply == null) {
            return Result.error("退货申请不存在");
        }

        // 2. 验证状态
        if (returnApply.getStatus() != 0) {
            return Result.error("该申请已处理，无法重复操作");
        }

        // 2. 查询该退货申请关联的所有退货申请项（包含订单项ID）
        List<ReturnApplyItem> returnApplyItems = returnApplyItemMapper.selectItemsByReturnId(returnId);
        if (CollectionUtils.isEmpty(returnApplyItems)) {
            throw new RuntimeException("退货申请未关联任何商品，无法处理");
        }

        // 3. 查询退货明细和对应订单项，计算退款金额
        List<ReturnApplyItem> returnItems = returnApplyService.queryItemsByReturnId(returnId);
        List<String> itemNos = returnItems.stream()
                .map(ReturnApplyItem::getItemNo)
                .collect(Collectors.toList());

        List<OrderItem> orderItems = orderItemService.lambdaQuery()
                .eq(OrderItem::getOrderId, returnApply.getOrderId())
                .in(OrderItem::getItemNo, itemNos)
                .list();

        Map<String, OrderItem> itemMap = orderItems.stream()
                .collect(Collectors.toMap(OrderItem::getItemNo, item -> item));

        BigDecimal refundAmount = calculateRefundAmount(returnItems, itemMap);

        // 4. 调用支付服务执行退款
        log.info("执行退款操作，订单号: {}, 退款金额: {}",
                returnApply.getOrderNo(), refundAmount);

        userService.lambdaUpdate()
                // 设置用户金额 = 当前金额 + 退款金额
                .setSql("money = money + " + refundAmount)
                // 条件：用户名匹配（根据实际场景调整条件字段，如用户ID）
                .eq(User::getId, userId)
                .update();
        User u = userService.getById(userId);
        OrderPay orderPay = new OrderPay();
        orderPay.setUserId(Integer.valueOf(userId));
        orderPay.setOrderNo(returnApply.getOrderNo());
        orderPay.setPayType("订单退款");
        orderPay.setPayMoney(refundAmount);
        orderPay.setMoney(u.getMoney());
        orderPay.setPayTime(LocalDateTime.now());
        boolean refundSuccess = orderPayService.save(orderPay);
        if (!refundSuccess) {
            log.error("支付平台退款失败，订单号: {}", returnApply.getOrderNo());
            throw new RuntimeException("退款失败，请稍后重试");
        }
        // 5. 更新退货申请状态为"已同意"
        returnApplyService.lambdaUpdate()
                .set(ReturnApply::getStatus, 1) // 1-已同意
                .set(ReturnApply::getUpdateTime, LocalDateTime.now())
                .eq(ReturnApply::getReturnId, returnId)
                .update();

        // 6. 更新订单和订单项状态
        updateOrderAndItemsAfterRefund(returnApply, returnItems, itemNos);

        return Result.success("退款成功", refundAmount);
    }

    /**
     * 退款后更新订单和订单项状态
     */
    private void updateOrderAndItemsAfterRefund(ReturnApply returnApply,
                                                List<ReturnApplyItem> returnItems,
                                                List<String> itemNos) {
        // 查询该订单的所有订单项
        List<OrderItem> allItems = orderItemService.lambdaQuery()
                .eq(OrderItem::getOrderId, returnApply.getOrderId())
                .list();

        // 判断是否为全部退款
        boolean isFullRefund = allItems.stream()
                .allMatch(item -> itemNos.contains(item.getItemNo()));

        // 更新订单状态
        if (isFullRefund) {
            orderService.lambdaUpdate()
                    .set(Order::getStatus, "refunded")
                    .eq(Order::getOrderId, returnApply.getOrderId())
                    .update();
        } else {
            orderService.lambdaUpdate()
                    .set(Order::getStatus, "completed")
                    .eq(Order::getOrderId, returnApply.getOrderId())
                    .update();
        }

        // 更新订单项状态为"已退款"
        orderItemService.lambdaUpdate()
                .set(OrderItem::getItemStatus, "refunded")
                .in(OrderItem::getItemNo, itemNos)
                .eq(OrderItem::getOrderId, returnApply.getOrderId())
                .update();
    }

    /**
     * 商家拒绝退款申请
     */
    @PostMapping("/reject/{returnId}")
    @Transactional
    public Result rejectRefund(
            @PathVariable Integer returnId,
            @RequestParam String reason) {

        // 1. 查询退货申请
        ReturnApply returnApply = returnApplyService.getById(returnId);
        if (returnApply == null) {
            return Result.error("退货申请不存在");
        }

        // 2. 验证状态
        if (returnApply.getStatus() != 0) {
            return Result.error("该申请已处理，无法重复操作");
        }

        // 3. 更新退货申请状态为"已拒绝"
        returnApplyService.lambdaUpdate()
                .set(ReturnApply::getStatus, 2) // 2-已拒绝
                .set(ReturnApply::getUpdateTime, LocalDateTime.now())
                .eq(ReturnApply::getReturnId, returnId)
                .update();

        // 4. 恢复订单和订单项状态
        List<ReturnApplyItem> refundItems = returnApplyService.queryItemsByReturnId(returnId);
        List<String> refundItemNos = refundItems.stream()
                .map(ReturnApplyItem::getItemNo)
                .collect(Collectors.toList());

        // 恢复订单项状态为已送达
        orderItemService.lambdaUpdate()
                .set(OrderItem::getItemStatus, "refund_rejected")
                .in(OrderItem::getItemNo, refundItemNos)
                .eq(OrderItem::getOrderId, returnApply.getOrderId())
                .update();

        // 恢复订单状态为已完成
        orderService.lambdaUpdate()
                .set(Order::getStatus, "refund_rejected")
                .eq(Order::getOrderId, returnApply.getOrderId())
                .update();

        return Result.success("已拒绝退款申请");
    }




}
